//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

import React, { useEffect, useState } from "react";
import { observer } from "mobx-react";
import { useGitStores } from "../store";
import { readDir, type FileEntry } from '@tauri-apps/api/fs';
import { resolve } from '@tauri-apps/api/path';
import { Breadcrumb, Button, Card, Form, Layout, List, Space } from "antd";
import { CloseOutlined, CloudDownloadOutlined, CloudUploadOutlined, FileOutlined, FolderOutlined } from "@ant-design/icons";
import { start, type WidgetInfo } from "@/api/widget";
import { download_file, get_cache_file, GLOBAL_WIDGET_STORE_FS_ID } from "@/api/fs";
import { get_session } from "@/api/user";
import { check_unpark, get_min_app_path, unpack_min_app } from "@/api/min_app";
import { uniqId } from "@/utils/utils";
import type { LocalRepoCommitForFileInfo } from "@/api/local_repo";
import { list_repo_commit_for_file } from "@/api/local_repo";
import moment from "moment";
import PullModal from "@/pages/GitSimple/components/PullModal";
import PushModal from "@/pages/GitSimple/components/PushModal";
import { appWindow, WebviewWindow } from "@tauri-apps/api/window";
import ChangeBranchOrTagModal from "@/pages/GitSimple/components/ChangeBranchOrTagModal";

interface GitFileInfoProps {
    curDirList: string[];
    fileName: string;
    onClose: () => void;
}

const GitFileInfo = observer((props: GitFileInfoProps) => {
    const store = useGitStores();

    const [matchWidget, setMatchWidget] = useState<WidgetInfo | null>();
    const [commitList, setCommitList] = useState<LocalRepoCommitForFileInfo[]>([]);

    const findWidget = async () => {
        const curFileName = await resolve(store.repoInfo?.path ?? "", ...props.curDirList, props.fileName);
        for (const widget of store.widgetList) {
            if (widget.file_list.includes(curFileName)) {
                setMatchWidget(widget);
                return;
            }
        }
        const pos = curFileName.lastIndexOf(".")
        if (pos == -1) {
            return null;
        }
        const ext = curFileName.substring(pos + 1);
        for (const widget of store.widgetList) {
            if (widget.extension_list.includes(ext)) {
                setMatchWidget(widget);
                return;
            }
        }
        setMatchWidget(null);
        return;
    }

    const startView = async () => {
        if (matchWidget == null) {
            return;
        }
        //下载文件
        const res = await get_cache_file(GLOBAL_WIDGET_STORE_FS_ID, matchWidget.file_id, "content.zip");
        let localFilePath = "";
        if (res.exist_in_local) {
            localFilePath = res.local_path;
        }
        if (localFilePath == "") {
            const sessionId = await get_session();
            const downloadRes = await download_file(sessionId, GLOBAL_WIDGET_STORE_FS_ID, matchWidget.file_id, "", "content.zip");
            localFilePath = downloadRes.local_path;
        }
        //解压文件
        const ok = await check_unpark(GLOBAL_WIDGET_STORE_FS_ID, matchWidget.file_id);
        if (!ok) {
            await unpack_min_app(GLOBAL_WIDGET_STORE_FS_ID, matchWidget.file_id, "");
        }
        const path = await get_min_app_path(GLOBAL_WIDGET_STORE_FS_ID, matchWidget.file_id);
        const filePath = await resolve(store.repoInfo?.path ?? '', ...props.curDirList, props.fileName);
        await start(`gw:${uniqId()}`, filePath, path, filePath);
    };

    const loadCommitList = async () => {
        const fileName = [...props.curDirList, props.fileName].join("/");
        const tmpList = await list_repo_commit_for_file(store.repoInfo?.path ?? "", `refs/heads/${store.headInfo?.branch_name ?? ""}`, fileName);
        setCommitList(tmpList);
    };

    const openCommitDiff = async (commit: LocalRepoCommitForFileInfo) => {
        const pos = await appWindow.innerPosition();
        new WebviewWindow(`commit:${commit.id}`, {
            url: `git_diff.html?path=${encodeURIComponent(store.repoInfo?.path ?? "")}&commitId=${commit.id}&summary=${encodeURIComponent(commit.summary)}&commiter=${encodeURIComponent(commit.commiter)}&fileName=${encodeURIComponent(commit.file_name)}`,
            title: `${store.repoInfo?.name ?? ""}(commit:${commit.id.substring(0, 8)})`,
            x: pos.x + Math.floor(Math.random() * 200),
            y: pos.y + Math.floor(Math.random() * 200),
        })
    };

    useEffect(() => {
        findWidget();
        loadCommitList();
    }, [props.curDirList, props.fileName]);

    return (
        <Card title="修改记录" headStyle={{ backgroundColor: "#eee" }}
            bodyStyle={{ padding: "0px 0px", height: "calc(100vh - 90px)", overflowY: "scroll" }}
            extra={
                <Space>
                    {matchWidget != null && (
                        <Button type="primary" onClick={e => {
                            e.stopPropagation();
                            e.preventDefault();
                            startView();
                        }}>查看内容</Button>
                    )}

                    <Button type="link" icon={<CloseOutlined />} onClick={e => {
                        e.stopPropagation();
                        e.preventDefault();
                        props.onClose();
                    }} />
                </Space>
            }>
            <List rowKey="id" dataSource={commitList} renderItem={commit => (
                <List.Item style={{ cursor: "pointer" }} onClick={e => {
                    e.stopPropagation();
                    e.preventDefault();
                    openCommitDiff(commit);
                }}>
                    <Card title={`${commit.commiter} ${moment(commit.time_stamp).format("YYYY-MM-DD HH:mm:ss")}`} style={{ width: "100%" }} bordered={false}
                        headStyle={{ backgroundColor: "#eee" }}>
                        <pre style={{ whiteSpace: "pre-wrap", wordWrap: "break-word" }}>
                            {commit.summary}
                        </pre>
                    </Card>
                </List.Item>
            )} split={false} />
        </Card>
    );
});

const WorkDir = () => {
    const store = useGitStores();

    const [curDirList, setCurDirList] = useState([] as string[]);
    const [fileEntryList, setFileEntryList] = useState([] as FileEntry[]);
    const [selFileName, setSelFileName] = useState("");

    const [showPullModal, setShowPullModal] = useState(false);
    const [showPushModal, setShowPushModal] = useState(false);

    const [showChangeBranchOrTagModal, setShowChangeBranchOrTagModal] = useState(false);

    const loadFileEntryList = async () => {
        if (store.repoInfo == null) {
            return;
        }
        const path = await resolve(store.repoInfo.path, ...curDirList);
        const tmpList = await readDir(path);
        setFileEntryList(tmpList.filter(item => item.name != null && item.name != ".git"));
    };

    useEffect(() => {
        if (store.repoInfo != null) {
            loadFileEntryList();
        }
    }, [curDirList, store.repoInfo]);

    return (
        <Card bordered={false} bodyStyle={{ height: "calc(100vh - 40px)", paddingTop: "2px", padding: "0px 0px" }}
            headStyle={{ backgroundColor: "#eee", height: "40px" }}
            title={
                <Space>
                    <span>当前路径:</span>
                    <Breadcrumb>
                        <Breadcrumb.Item>
                            <Button type="link" disabled={curDirList.length == 0} onClick={e => {
                                e.stopPropagation();
                                e.preventDefault();
                                setCurDirList([]);
                            }}>
                                根目录
                            </Button>
                        </Breadcrumb.Item>
                        {curDirList.map((name, index) => (
                            <Breadcrumb.Item key={index}>
                                <Button type="link" disabled={(index + 1) == curDirList.length}
                                    onClick={e => {
                                        e.stopPropagation();
                                        e.preventDefault();
                                        setCurDirList(curDirList.slice(0, index + 1));
                                    }}>
                                    {name}
                                </Button>
                            </Breadcrumb.Item>
                        ))}
                    </Breadcrumb>
                </Space>
            }
            extra={
                <Space size="large">
                    <Form layout="inline">
                        {store.headInfo?.detached == false && (
                            <Form.Item label="当前分支">
                                <Button type="link" onClick={e => {
                                    e.stopPropagation();
                                    e.preventDefault();
                                    setShowChangeBranchOrTagModal(true);
                                }}>{store.headInfo?.branch_name}</Button>
                            </Form.Item>
                        )}

                        {store.headInfo?.detached == true && (
                            <Form.Item label="当前标记">
                                <Button type="link" onClick={e => {
                                    e.stopPropagation();
                                    e.preventDefault();
                                    setShowChangeBranchOrTagModal(true);
                                }}>{store.headInfo?.tag_name}</Button>
                            </Form.Item>
                        )}
                    </Form>
                    <Button type="link" icon={<CloudDownloadOutlined style={{ fontSize: "24px" }} />} title="pull"
                        onClick={e => {
                            e.stopPropagation();
                            e.preventDefault();
                            setShowPullModal(true);
                        }} />
                    <Button type="link" icon={<CloudUploadOutlined style={{ fontSize: "24px" }} />} title="push"
                        onClick={e => {
                            e.stopPropagation();
                            e.preventDefault();
                            setShowPushModal(true);
                        }} />
                </Space>
            }>
            <Layout style={{ height: "100%", backgroundColor: "white" }}>
                <Layout.Content>
                    <List rowKey="name" dataSource={fileEntryList} pagination={false}
                        grid={{ gutter: 16 }}
                        style={{ width: "100%", padding: "10px", paddingRight: selFileName == "" ? "250px" : "0px", height: "calc(100vh - 40px)", overflowY: "scroll" }}
                        renderItem={entry => (
                            <List.Item style={{ width: "250px" }}>
                                <Space style={{ fontSize: "16px", paddingLeft: "10px", borderRadius: "10px", backgroundColor: selFileName == entry.name ? "#eee" : undefined, }}>
                                    {entry.children != null && <FolderOutlined />}
                                    {entry.children == null && <FileOutlined />}
                                    {entry.children != null && (
                                        <a onClick={e => {
                                            e.stopPropagation();
                                            e.preventDefault();
                                            setCurDirList([...curDirList, entry.name ?? ""]);
                                            setSelFileName("");
                                        }} title={entry.name ?? ""}
                                            style={{ display: "inline-block", width: "200px", overflow: "hidden", textAlign: "left", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{entry.name}</a>
                                    )}
                                    {entry.children == null && (
                                        <a onClick={e => {
                                            e.stopPropagation();
                                            e.preventDefault();
                                            setSelFileName(entry.name ?? "");
                                        }} title={entry.name ?? ""}
                                            style={{ display: "inline-block", width: "200px", overflow: "hidden", textAlign: "left", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>{entry.name}</a>
                                    )}
                                </Space>
                            </List.Item>
                        )} />
                </Layout.Content>
                {selFileName != "" && (
                    <Layout.Sider theme="light" style={{ borderLeft: "1px solid #e4e4e8", padding: "0px 0px" }} width={250}>
                        <GitFileInfo curDirList={curDirList} fileName={selFileName} onClose={() => setSelFileName("")} />
                    </Layout.Sider>
                )}
            </Layout>
            {showPullModal == true && store.repoInfo != null && store.headInfo != null && (
                <PullModal repoPath={store.repoInfo.path} headBranch={store.headInfo.branch_name} onClose={() => setShowPullModal(false)} userName={store.userName} />
            )}
            {showPushModal == true && store.repoInfo != null && store.headInfo != null && (
                <PushModal repoPath={store.repoInfo.path} headBranch={store.headInfo.branch_name} onClose={() => setShowPushModal(false)} userName={store.userName} />
            )}
            {showChangeBranchOrTagModal == true && store.repoInfo != null && store.headInfo != null && (
                <ChangeBranchOrTagModal headInfo={store.headInfo} repo={store.repoInfo}
                    onCancel={() => setShowChangeBranchOrTagModal(false)}
                    onOk={() => {
                        setShowChangeBranchOrTagModal(false);
                        store.loadHeadInfo();
                    }} />
            )}
        </Card>
    );
};

export default observer(WorkDir);